<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-microsoft-com:vml" >
  <head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8"/>
    <title>L+M Adventures</title>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.21/jquery-ui.min.js"></script>
    <script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>
    <script type="text/javascript" src="http://maps.googleapis.com/maps/api/js?libraries=places&sensor=false"></script>
    
    <style type="text/css">
    body {
    	font-family: Verdana, Arial, sans serif;
    	font-size: 11px;
    	margin: 0px;
    	padding: 0px;
    }
    table.directions th {
    background-color:#EEEEEE;
    }
    img {
    	color: #000000;
    }
    </style>
    
    
    <script language="javascript">
    	// global waypoint counter and array of waypoints
    	var waypoint_count = 0;
    	var waypoints = new Array();
    	
    	// Create function get get object size (works on arrays and associative, too) 
    	Object.size = function(obj) {
            var size = 0, key;
            for (key in obj) {
                if (obj.hasOwnProperty(key)) size++;
            }
            return size;
        };
    </script>
    
    <script type="text/javascript">
    
    var directionsService;
    var map;
    var oldDirections = [];
    var currentDirections = null;
    var responseGlobal=null;
    var markers = []; // markers 
    var itineraryMarkers = []; // itinerary markers 
    var routes = [];
    var waypointData = new Array();
    var itineraryMaps = [];
    
    function initialize() {
    	
    	// Initialize Google Map 
   	  	var myMapOptions = {
			zoom: 1,
			center: new google.maps.LatLng(-33.879, 151.235),
   			mapTypeId: google.maps.MapTypeId.ROADMAP
   		}
        map = new google.maps.Map(document.getElementById("map_canvas"), myMapOptions);
    	
    	// Initialize directions service
   	 	directionsService = new google.maps.DirectionsService();
    	
    	// Initialize places service
    	placesService = new google.maps.places.PlacesService(map);

	    //setUndoDisabled(true);

	    /*
	    // Get stops along adventure
        var routepoints = new Array();
    	for(var i in waypoints) {
    		var waypoint = waypoints[i];
    		//alert(waypoint);
    		var waypoint_id = '#' + waypoint;
    		var routepoint = $(waypoint_id).val();
    		if(routepoint != null){
    		routepoints.push({ location: routepoint});}
    	}
    	//alert(routepoints);
	    calcRoute("San Francisco", "Mountain View", routepoints, 'store');
	    */
	    google.maps.event.addListener(map, 'zoom_changed', function() {
	        // 3 seconds after the center of the map has changed, pan back to the
	        // marker.
	        updateRouteZoom();
	      });
	    google.maps.event.addListener(map, 'center_changed', function() {
	        // 3 seconds after the center of the map has changed, pan back to the
	        // marker.
	        updateRouteZoom();
	      });

	    updateRoute();
    }
    
    function initializeItinerary() {
    	
    	// Initialize array of itinerary markers 
    	itineraryMarkers = new Array(Object.size(waypointData) - 1); // TODO: Update this depending on how many maps we display in the itinerary.  The size of this array should equal the number of maps shown in the itinerary.
    	//alert('itineraryMarkers = ' + Object.size(itineraryMarkers));
    	
    	$.each(waypointData, function(index, value) {
    		if(index > 0) {
    			
    			// Initialize Google Map 
		   	  	var myMapOptions = {
					zoom: 1,
					center: new google.maps.LatLng(-33.879, 151.235),
		   			mapTypeId: google.maps.MapTypeId.ROADMAP
		   		}
    			
    			var mapCanvasStart = document.getElementById("map_canvas_" + index);
		        var itineraryMap = new google.maps.Map(mapCanvasStart, myMapOptions);
		        var directionsDisplay = new google.maps.DirectionsRenderer({
		 	        'map': itineraryMap,
		 	        'preserveViewport': false,
		 	        'draggable': true
		 	    });
		        
		        // alert(waypointData[index].location);
		        directionsDisplay.setPanel(document.getElementById("directions_panel_" + index ));
		        var value = {
		        	'destination': waypointData[index].location,
		 	        'origin':  waypointData[index-1].location,
		 	        'travelMode':getTravelMode(waypointData[index-1].travel_mode)
		 	    };
		        
		        //alert(value);
		        // var value = directionsDisplay.getDirections()
		        directionsService.route(value, function(response, status) {
		        	if (status == google.maps.DirectionsStatus.OK) {
		        		directionsDisplay.setDirections(response);
		        	}
		        });
		        
		        //	directionsDisplay.setDirections(responseGlobal);
		        itineraryMaps.push(itineraryMap);
		    }
    		
    		// Initialize waypoint array 
    		itineraryMarkers[index-1] = new Array();
    		//alert('itineraryMarkers[' + Object.size(itineraryMarkers[index-1]) + '] = ' + Object.size(itineraryMarkers));
    		alert('size(itineraryMarkers[' + Object.size(itineraryMarkers[index-1]) + ']) = ' + Object.size(itineraryMarkers[index-1]));
    	});
    	
    	alert('size(itineraryMarkers) = ' + Object.size(itineraryMarkers));
    }
    
    function calcRoute(routes, keyword) {
        
        //alert(Object.size(routes));
    	
    	// Iterate through routes and draw them on the map
    	$.each(routes, function(index, value) {
    		// Create directions display 
            var directionsDisplay = new google.maps.DirectionsRenderer({
    	        'map': map,
    	        'preserveViewport': false,
    	        'draggable': true
    	    });
    		
    		// Render directions 
    	    directionsDisplay.setPanel(document.getElementById("directions_panel"));
            
    	    // Set up listener for directions display 
    	    google.maps.event.addListener(directionsDisplay, 'directions_changed',
       	      function() {
       	        /* if (currentDirections) {
       	          oldDirections.push(currentDirections);
       	          setUndoDisabled(false);
       	        } */
       	        currentDirections = directionsDisplay.getDirections();
       	        // TODO: update nearby places here? 
       	      });
            
            // Create route on map
            directionsService.route(value, function(response, status) {
              if (status == google.maps.DirectionsStatus.OK) {
                directionsDisplay.setDirections(response); // Set directions on map
                responseGlobal = response;
                // Get places along route
                for (var i in response.routes) { // get route 
                	var pathPoints = new Array();
                	for (var j in response.routes[i].legs) { // get leg of route (path between two waypoints)
                		for (var k in response.routes[i].legs[j].steps) { // get steps along route, the individual points
                			var stepPoints = google.maps.geometry.encoding.decodePath(response.routes[i].legs[j].steps[k].polyline.points); // get (decoded) array of points that define polyline
                			for (var l in stepPoints) {
                				pathPoints.push(stepPoints[l]);
                				//console.log(stepPoints[l]);
                			}
                		}
                	}
                
                	findPlacesByKeyword(pathPoints, keyword);
                	//findPlacesByKeyword(pathPoints, keyword);
                }
              }
            });
    	});
      }

	// Computes distance between two points
	function distance(a, b) {
		return Math.sqrt(Math.pow(a.lat() - b.lat(), 2) + Math.pow(a.lng() - b.lng(), 2));
	}
	
	function updateRouteZoom() {
		var keyword = $('#place_keyword').val();
		if(responseGlobal != null) {
			for (var i in responseGlobal.routes) { // get route 
	        	var pathPoints = new Array();
	        	for (var j in responseGlobal.routes[i].legs) { // get leg of route (path between two waypoints)
	        		for (var k in responseGlobal.routes[i].legs[j].steps) { // get steps along route, the individual points
	        			var stepPoints = google.maps.geometry.encoding.decodePath(responseGlobal.routes[i].legs[j].steps[k].polyline.points); // get (decoded) array of points that define polyline
	        			for (var l in stepPoints) {
	        				pathPoints.push(stepPoints[l]);
	        			}
	        		}
	        	}
	        	
	        	findPlacesByKeywordZoom(pathPoints, keyword);
	        	//findPlacesByKeyword(pathPoints, keyword);
	        }
		} else {
			alert("hi");
		}
	}
	
	function addPlaces(placetype) {
		clearWaypoints();
		var keyword = $('#place_keyword').val();
		if(responseGlobal != null) {
			for (var i in responseGlobal.routes) { // get route 
	        	var pathPoints = new Array();
	        	for (var j in responseGlobal.routes[i].legs) { // get leg of route (path between two waypoints)
	        		for (var k in responseGlobal.routes[i].legs[j].steps) { // get steps along route, the individual points
	        			var stepPoints = google.maps.geometry.encoding.decodePath(responseGlobal.routes[i].legs[j].steps[k].polyline.points); // get (decoded) array of points that define polyline
	        			for (var l in stepPoints) {
	        				pathPoints.push(stepPoints[l]);
	        			}
	        		}
	        	}
	        
	        	findPlacesByKeywordZoomType(placetype,pathPoints, keyword);
	        	//findPlacesByKeyword(pathPoints, keyword);
	        }
		} else {
			alert("hi");
		}
	}
	
	function addPlacesItinerary(placetype, index) {
		//clearWaypoints();
		clearItineraryWaypoints(index-1);
		var keyword = $('#place_keyword').val();
		if(responseGlobal != null) {
			for (var i in responseGlobal.routes) { // get route 
	        	var pathPoints = new Array();
	        	for (var j in responseGlobal.routes[i].legs) { // get leg of route (path between two waypoints)
	        		for (var k in responseGlobal.routes[i].legs[j].steps) { // get steps along route, the individual points
	        			var stepPoints = google.maps.geometry.encoding.decodePath(responseGlobal.routes[i].legs[j].steps[k].polyline.points); // get (decoded) array of points that define polyline
	        			for (var l in stepPoints) {
	        				pathPoints.push(stepPoints[l]);
	        			}
	        		}
	        	}
	        
	        	findPlacesByKeywordZoomTypeIntin(placetype, pathPoints, keyword, index-1);
	        	//findPlacesByKeyword(pathPoints, keyword);
	        }
		} else {
			alert("hi");
		}
	}
	/* function dist (point, lastpoint){
		  return sqrt((point.lat()-lastpoint.lat())^2+(point.lng()-lastpoint.lng())^2);
		} */
	</script>
    
    
    
    
    
    
    <script language="javascript">
    
    	function addWaypoint(name) {
    		
    		//var table = document.getElementById("sortable");
    		var waypoint_box = 'waypoint_' + waypoint_count +"_box";
            var waypoint_name = 'waypoint_' + waypoint_count;
            //var rowCount = table.rows.length;
            $(".sortable").append("<li class = "+waypoint_box+" id = "+waypoint_box+"><span></span> </li>");
            var row = $("."+waypoint_box);
            //var cell1 = row.append(0);
           
            row.append("<input class = checkbox" + waypoint_count+" type=checkbox id=checkbox" + waypoint_count +"></input>");
 
            //var cell2 = row.insertCell(1);
            //cell2.innerHTML = rowCount + 1;
            //cell2.innerHTML = waypoint_count;
 
            //var cell3 = row.insertCell(2);
            var element2 = document.createElement("input");
            element2.type = "text";
            var waypoint_name = 'waypoint_' + waypoint_count;
            element2.name = waypoint_name;
            element2.setAttribute('id', waypoint_name); // set waypoint ID
            $(element2).val(name);
            row.append(element2);
            
            //waypoints.push(waypoint_name);
            waypoints[waypoint_name] = waypoint_name;
            waypoint_count++;
           
    	}
    
        function addRow(tableID) {
 
            //var table = document.getElementById("sortable");
            var waypoint_box = 'waypoint_' + waypoint_count +"_box";
            var waypoint_name = 'waypoint_' + waypoint_count;
            //var rowCount = table.rows.length;
            $(".sortable").append("<li class = " + waypoint_box + " id = " + waypoint_box + "><span></span> </li>");
            var row = $("." + waypoint_box);
            //var cell1 = row.append(0);
           
            row.append("<input class = checkbox" + waypoint_count+" type=checkbox id=checkbox" + waypoint_count +"></input>");
 
            //var cell2 = row.insertCell(1);
            //cell2.innerHTML = rowCount + 1;
            //cell2.innerHTML = waypoint_count;
 
            //var cell3 = row.insertCell(2);
            var element2 = document.createElement("input");
            element2.type = "text";
            var waypoint_name = 'waypoint_' + waypoint_count;
            element2.name = waypoint_name;
            element2.setAttribute('id', waypoint_name); // set waypoint ID
            row.append(element2);
            
            // add dropdown of travel type to this waypoint
            var waypoint_travel_type = waypoint_name + '_travel';
            row.append("<select name=\"" + waypoint_travel_type + "\" id=\"" + waypoint_travel_type + "\"><option>Driving</option><option>Transit</option><option>Walking</option><option>Bicycling</option></select>");
            
            //waypoints.push(waypoint_name);
            waypoints[waypoint_name] = waypoint_name;
            waypoint_count++;
 
        }
 
        function deleteRow(tableID) {
            try {
	            //var table = document.getElementById(tableID);
	            //var rowCount = table.rows.length;
	 			//alert(waypoint_count);
	            for(var i=0; i<waypoint_count; i++) {
	                var chkbox = document.getElementById("checkbox"+i);
	              //  alert(".checkbox"+i)
	                //alert(document.getElementById("checkbox"+i).checked);
	                if(null != chkbox && true == chkbox.checked) {
	                    
	                    
	                    var waypoint_name = 'waypoint_' + i;
	                    $("."+waypoint_name).remove();
	                    
	                    delete waypoints[waypoint_name+"_box"];
	                    
	                    var size = Object.size(waypoints);
	                    //alert(size);
	                    
	                    //table.deleteRow(i);
	                    
	                    //rowCount--;
	                    //i--;
	                }
	 
	 
	            }
            } catch(e) {
                alert(e);
            }
        }
        
	/*function getPlacesByAddress(address) {
		var place_keyword = $('#place_keyword').val(); // get place keyword
	    var geo = new google.maps.Geocoder;
	
	    geo.geocode({ 'address': address }, function(results, status) {
	            if (status == google.maps.GeocoderStatus.OK) {
	            	
	            	findPlacesByKeyword(results[0].geometry.location, place_keyword);
	            	
	              //return results[0].geometry.location;
	            } else {
	              alert("Geocode was not successful for the following reason: " + status);
	            }
	     });
	}*/
        	
	
	
	
	
        		
	function findPlacesByKeywordCircle(location, keyword, radius) {
		
		var request = {
		    //location: new google.maps.LatLng(-33.8665433, 151.1956316),
		    location: location,
		    radius: radius,
		    //types: ['store'],
			name: keyword
		};
		
		placesService.search(request, function(results, status) {
			if (status == google.maps.places.PlacesServiceStatus.OK) {
				for (var i = 0; i < results.length; i++) {
					var place = results[i];
					
					createWaypointMarker(results[i]);
				}
			} else if (status == google.maps.places.PlacesServiceStatus.OVER_QUERY_LIMIT) {
				//alert("Over quota");
				console.log("Calling findPlacesByKeywordCircle due to OVER_QUERY_LIMIT");
				setTimeout(function() { findPlacesByKeywordCircle(location, keyword, radius); }, 50);
			}
		});
	}
	
	
	
	
	
	/*
	function findPlacesByKeyword(placePoints, keyword) {
		var lastPointDrawn = 0;
		//findPlacesByKeywordCircle(placePoints[0], keyword, 5000);
		//alert(placePoints[0])
		for ( var l in placePoints) {
			// Check if distance betwen two points exceeds certain distance threshold, if so, search for more stuff
			var degreesOfLongOrLat = 0.1;
			if (distance(placePoints[lastPointDrawn],
					placePoints[l]) > degreesOfLongOrLat) {
				findPlacesByKeywordCircle(placePoints[l],
						keyword, 5000);
				var lastPointDrawn = l;
			}
		}
	}
	*/
	
	function findPlacesByKeyword(placePoints, keyword) {
console.log("called findPlacesByKeyword");
		
		var numpoint = 10; // number of points to divide path by
		var width = .01;
		
		var pcrop = polylinePathInWindow(placePoints); // cropped polyline path
		
		if(Object.size(pcrop) > 0) {
			var lastpoint = 0;
			var expandLatLngBounds = new google.maps.LatLngBounds(pcrop[0], pcrop[0]);
			var calculatedDistance = distance(pcrop[0], pcrop[Object.size(pcrop) - 1]) / numpoint;
			console.log("calcdistance" +  calculatedDistance);
			for (var point in pcrop) {
			  
			  var distanceThreshold = distance(pcrop[point], pcrop[lastpoint]);
			  expandLatLngBounds.extend(pcrop[point]);
			  if (distanceThreshold > calculatedDistance) {
				  
				  var r = createrectangle(expandLatLngBounds.getNorthEast().lat(), expandLatLngBounds.getNorthEast().lng(), expandLatLngBounds.getSouthWest().lat(), expandLatLngBounds.getSouthWest().lng(), width);
				
				  findPlacesByKeywordRectangle(r, keyword);
				  var lastpoint = point;
				  expandLatLngBounds = new google.maps.LatLngBounds(pcrop[lastpoint], pcrop[lastpoint]);
				 // var distanceThreshold = 0;
			  }
			 
			}
			
			var r = createrectangle(pcrop[Object.size(pcrop)-1].lat(), pcrop[Object.size(pcrop)-1].lng(), pcrop[lastpoint].lat(), pcrop[lastpoint].lng(), width);
			
			findPlacesByKeywordRectangle(r, keyword);
		}
	}
	function findPlacesByKeywordZoom(placePoints, keyword) {
		console.log("called findPlacesByKeyword");
		
		var numpoint = 10; // number of points to divide path by
		var width = .01;
		
		var pcrop = polylinePathInWindowZoom(placePoints); // cropped polyline path
		
		if(Object.size(pcrop) > 0) {
			var lastpoint = 0;
			var expandLatLngBounds = new google.maps.LatLngBounds(pcrop[0], pcrop[0]);
			var calculatedDistance = distance(pcrop[0], pcrop[Object.size(pcrop) - 1]) / numpoint;
			console.log("calcdistance" +  calculatedDistance);
			for (var point in pcrop) {
			  
			  var distanceThreshold = distance(pcrop[point], pcrop[lastpoint]);
			  expandLatLngBounds.extend(pcrop[point]);
			  if (distanceThreshold > calculatedDistance) {
				  
				  var r = createrectangle(expandLatLngBounds.getNorthEast().lat(), expandLatLngBounds.getNorthEast().lng(), expandLatLngBounds.getSouthWest().lat(), expandLatLngBounds.getSouthWest().lng(), width);
				
				  findPlacesByKeywordRectangle(r, keyword);
				  var lastpoint = point;
				  expandLatLngBounds = new google.maps.LatLngBounds(pcrop[lastpoint], pcrop[lastpoint]);
				 // var distanceThreshold = 0;
			  }
			 
			}
			
			var r = createrectangle(pcrop[Object.size(pcrop)-1].lat(), pcrop[Object.size(pcrop)-1].lng(), pcrop[lastpoint].lat(), pcrop[lastpoint].lng(), width);
			
			findPlacesByKeywordRectangle(r, keyword);
		}
	}
	function findPlacesByKeywordZoomType(type, placePoints, keyword) {
		console.log("called findPlacesByKeyword");
		
		var numpoint = 10; // number of points to divide path by
		var width = .01;
		
		var pcrop = polylinePathInWindowZoom(placePoints); // cropped polyline path
		
		if(Object.size(pcrop) > 0) {
			var lastpoint = 0;
			var expandLatLngBounds = new google.maps.LatLngBounds(pcrop[0], pcrop[0]);
			var calculatedDistance = distance(pcrop[0], pcrop[Object.size(pcrop) - 1]) / numpoint;
			console.log("calcdistance" +  calculatedDistance);
			for (var point in pcrop) {
			  
			  var distanceThreshold = distance(pcrop[point], pcrop[lastpoint]);
			  expandLatLngBounds.extend(pcrop[point]);
			  if (distanceThreshold > calculatedDistance) {
				  
				  var r = createrectangle(expandLatLngBounds.getNorthEast().lat(), expandLatLngBounds.getNorthEast().lng(), expandLatLngBounds.getSouthWest().lat(), expandLatLngBounds.getSouthWest().lng(), width);
				
				  findPlacesByKeywordRectangleType(type, r, keyword);
				  var lastpoint = point;
				  expandLatLngBounds = new google.maps.LatLngBounds(pcrop[lastpoint], pcrop[lastpoint]);
				 // var distanceThreshold = 0;
			  }
			 
			}
			
			var r = createrectangle(pcrop[Object.size(pcrop)-1].lat(), pcrop[Object.size(pcrop)-1].lng(), pcrop[lastpoint].lat(), pcrop[lastpoint].lng(), width);
			
			findPlacesByKeywordRectangleType(type, r, keyword);
		}
	}
	function findPlacesByKeywordZoomTypeIntin(type, placePoints, keyword, index) {
		console.log("called findPlacesByKeyword");
		
		var numpoint = 10; // number of points to divide path by
		var width = .01;
		
		var pcrop = polylinePathInWindowZoom(placePoints); // cropped polyline path
		
		if(Object.size(pcrop) > 0) {
			var lastpoint = 0;
			var expandLatLngBounds = new google.maps.LatLngBounds(pcrop[0], pcrop[0]);
			var calculatedDistance = distance(pcrop[0], pcrop[Object.size(pcrop) - 1]) / numpoint;
			console.log("calcdistance" +  calculatedDistance);
			for (var point in pcrop) {
			  
			  var distanceThreshold = distance(pcrop[point], pcrop[lastpoint]);
			  expandLatLngBounds.extend(pcrop[point]);
			  if (distanceThreshold > calculatedDistance) {
				  
				  var r = createrectangle(expandLatLngBounds.getNorthEast().lat(), expandLatLngBounds.getNorthEast().lng(), expandLatLngBounds.getSouthWest().lat(), expandLatLngBounds.getSouthWest().lng(), width);
				
				  findPlacesByKeywordRectangleTypeIntin(type, r, keyword,index);
				  var lastpoint = point;
				  expandLatLngBounds = new google.maps.LatLngBounds(pcrop[lastpoint], pcrop[lastpoint]);
				 // var distanceThreshold = 0;
			  }
			 
			}
			
			var r = createrectangleIntin(pcrop[Object.size(pcrop)-1].lat(), pcrop[Object.size(pcrop)-1].lng(), pcrop[lastpoint].lat(), pcrop[lastpoint].lng(), width);
			findPlacesByKeywordRectangleTypeIntin(type, r, keyword,index);
		}
	}
	function findPlacesByKeywordRectangle(bounds, keyword) {
		
		var request = {
		    //location: new google.maps.LatLng(-33.8665433, 151.1956316),
		    //types: ['store'],
		    bounds: bounds,
			name: keyword
		};
		
		placesService.search(request, function(results, status) {
			if (status == google.maps.places.PlacesServiceStatus.OK) {
				for (var i = 0; i < results.length; i++) {
					var place = results[i];
					
					createWaypointMarker(results[i]);
				}
			} else if (status == google.maps.places.PlacesServiceStatus.OVER_QUERY_LIMIT) {
				console.log("Calling findPlacesByKeywordCircle due to OVER_QUERY_LIMIT");
				setTimeout(function() { findPlacesByKeywordRectangle(bounds,keyword); }, 500);
			} 
		});
	}
	
function findPlacesByKeywordRectangleType(type, bounds, keyword) {
		var typeArray = new Array();
		typeArray.push(type);
		var request = {
		    //location: new google.maps.LatLng(-33.8665433, 151.1956316),
		    //types: ['store'],
		    bounds: bounds,
			//name: keyword,
			types: typeArray
		};
		
		placesService.search(request, function(results, status) {
			if (status == google.maps.places.PlacesServiceStatus.OK) {
				for (var i = 0; i < results.length; i++) {
					var place = results[i];
					
					createWaypointMarker(results[i]);
				}
			} else if (status == google.maps.places.PlacesServiceStatus.OVER_QUERY_LIMIT) {
				console.log("Calling findPlacesByKeywordCircle due to OVER_QUERY_LIMIT");
				setTimeout(function() { findPlacesByKeywordRectangleType(type, bounds,keyword); }, 500);
			} 
		});
	}
	
function findPlacesByKeywordRectangleTypeIntin(type, bounds, keyword,index) {
	var typeArray = new Array();
	typeArray.push(type);
	var request = {
	    //location: new google.maps.LatLng(-33.8665433, 151.1956316),
	    //types: ['store'],
	    bounds: bounds,
		//name: keyword,
		types: typeArray
	};
	//alert(index);
	var placesServiceItin = new google.maps.places.PlacesService(itineraryMaps[index]);
	placesServiceItin.search(request, function(results, status) {
		if (status == google.maps.places.PlacesServiceStatus.OK) {
			for (var i = 0; i < results.length; i++) {
				var place = results[i];
				
				createWaypointMarkerIntin(results[i],index);
			}
		} else if (status == google.maps.places.PlacesServiceStatus.OVER_QUERY_LIMIT) {
			console.log("Calling findPlacesByKeywordCircle due to OVER_QUERY_LIMIT");
			setTimeout(function() { findPlacesByKeywordRectangleTypeIntin(type, bounds,keyword,index); }, 500);
		} 
	});
}
	
	function polylinePathInWindow(placePoints) {
		var bounds = map.getBounds();
		var placePointsCrop = new Array();
		for (var point in placePoints) {
			if (bounds.contains(placePoints[point])) {
				placePointsCrop.push(placePoints[point]);
			}
		}
		return placePoints;
		//TODO: implement zoom in feature
	}
	function polylinePathInWindowZoom(placePoints) {
		var bounds = map.getBounds();
		//alert(placePoints);
		var placePointsCrop = new Array();
		for (var point in placePoints) {
			//alert(placePoints[point]);
			if (bounds.contains(placePoints[point])) {
				//alert (point);
				placePointsCrop.push(placePoints[point]);
			}
		}
		return placePointsCrop;
		//TODO: implement zoom in feature 
	}
	
	function createrectangle(x0, y0, x1, y1, width) {
		console.log("createrectangle called");
		
		//var h = Math.sqrt(Math.pow((x1 - x0), 2) + Math.pow((y1 - y0), 2));
		
		//if (h == 0) {
			//return new google.maps.LatLngBounds(new google.maps.LatLng(x0, y0), new google.maps.LatLng(x1, y1));
		//}
		
		//var o = Math.abs(y1 - y0);
		//var a = Math.abs(x1 - x0);
		
		if(x1 > x0) {
			var swLat = x0 - width //* o / h;
			var neLat = x1 + width //* o / h;
		} else {
			var swLat = x1 - width //* o / h;
			var neLat = x0 + width //* o / h;
		}
		
		if(y1 > y0) {
			var swLng = y0 - width //* a / h;
			var neLng = y1 + width //* a / h;
		} else {
			var swLng = y1 - width //* a / h;
			var neLng = y0 + width //* a / h;
		}
		
		console.log("created rectangle (" + swLat + ", " + swLng + "), (" + neLat + ", " + neLng + ")");
		
		// Draw bounding rectangle 
	    var nebound = new google.maps.LatLng(neLat, neLng);
	    var swbound = new google.maps.LatLng(swLat, swLng);
	    var crbounds = new google.maps.LatLngBounds(swbound, nebound);
	    var rectangle = new google.maps.Rectangle();
	    var rectOptions = {
			strokeColor: "#FF0000",
			strokeOpacity: 0.5,
			strokeWeight: 2,
			fillColor: "#FF0000",
			fillOpacity: 0.35,
			map: map,
			bounds: crbounds
		};
		rectangle.setOptions(rectOptions);
	    
		return crbounds;
	}
	function createrectangleIntin(x0, y0, x1, y1, width) {
		console.log("createrectangle called");
		
		//var h = Math.sqrt(Math.pow((x1 - x0), 2) + Math.pow((y1 - y0), 2));
		
		//if (h == 0) {
			//return new google.maps.LatLngBounds(new google.maps.LatLng(x0, y0), new google.maps.LatLng(x1, y1));
		//}
		
		//var o = Math.abs(y1 - y0);
		//var a = Math.abs(x1 - x0);
		
		if(x1 > x0) {
			var swLat = x0 - width //* o / h;
			var neLat = x1 + width //* o / h;
		} else {
			var swLat = x1 - width //* o / h;
			var neLat = x0 + width //* o / h;
		}
		
		if(y1 > y0) {
			var swLng = y0 - width //* a / h;
			var neLng = y1 + width //* a / h;
		} else {
			var swLng = y1 - width //* a / h;
			var neLng = y0 + width //* a / h;
		}
		
		console.log("created rectangle (" + swLat + ", " + swLng + "), (" + neLat + ", " + neLng + ")");
		
		// Draw bounding rectangle 
	    var nebound = new google.maps.LatLng(neLat, neLng);
	    var swbound = new google.maps.LatLng(swLat, swLng);
	    var crbounds = new google.maps.LatLngBounds(swbound, nebound);
	    
		return crbounds;
	}
	
	
	if(!Array.prototype.indexOf) {
	    Array.prototype.indexOf = function(needle) {
	        for(var i = 0; i < this.length; i++) {
	            if(this[i] === needle) {
	                return i;
	            }
	        }
	        return -1;
	    };
	}
	
	
	function createWaypointMarkerIntin(place, index) {
		var placeLoc = place.geometry.location;
		var marker = new google.maps.Marker({
			map: itineraryMaps[index],
			position: place.geometry.location
		});
		
		// Add marker to the list of markers
		//itineraryMarkers.push(marker);
		//alert(itineraryMarkers.indexOf(index));
		/*
		if(itineraryMarkers.indexOf(index) <= -1) {
			itineraryMarkers[index] = new Array();
		}
		*/
		//a = itineraryMarkers[index];
		//alert(index);
		//alert(itineraryMarkers[index]);
		//alert("before: "+Object.size(a));
		//a.push(marker);
		//alert(Object.size(a));
		
		itineraryMarkers[index].push(marker);
		//alert(Object.size(itineraryMarkers[index]));
		if (index < 3) {
			alert('size(itineraryMarkers[' + index + ']) = ' + Object.size(itineraryMarkers[index]));
		}
		
		google.maps.event.addListener(marker, 'click', function() {
			var infowindow = new google.maps.InfoWindow({
				content: '<b>' + place.name + '</b><br /><a href="javascript:addWaypoint(\'' + place.vicinity + '\');">Add as waypoint</a>'
			});
			infowindow.open(itineraryMaps[index], this);
		});
	}
	
	
	
	
	function createWaypointMarker(place) {
		var placeLoc = place.geometry.location;
		var marker = new google.maps.Marker({
			map: map,
			position: place.geometry.location
		});
		
		// Add marker to the list of markers
		markers.push(marker);
	
		google.maps.event.addListener(marker, 'click', function() {
			var infowindow = new google.maps.InfoWindow({
				content: '<b>' + place.name + '</b><br /><a href="javascript:addWaypoint(\'' + place.vicinity + '\');">Add as waypoint</a>'
			});
			infowindow.open(map, this);
		});
	}
	
	function clearRoutes() {
		routes = [];
	}
	
	function clearWaypoints() {
		  if (markers) {
		    for (i in markers) {
		      markers[i].setMap(null);
		    }
		  }
		}
	
	/* function clearItineraryWaypoints() {
		  if (itineraryMarkers) {
		    for (i in itineraryMarkers) {
		    	for (j in itineraryMarkers[i]) {
		    		itineraryMarkers[i].setMap(null);
		    	}
		    }
		  }
		} */
	
	function clearItineraryWaypoints(i) {
		console.log("clearItineraryWaypoints called");
		//alert(i);
		//alert(itineraryMarkers[i]);
		//itineraryMarkers[i].push(marker);
		if(itineraryMarkers[i]) {
			//alert('size(itineraryMarkers[' + Object.size(itineraryMarkers[index-1]) + ']) = ' + Object.size(itineraryMarkers[index-1]));	
			for(j in itineraryMarkers[i]) {
				//alert(j);
				itineraryMarkers[i][j].setMap(null);
			}
		}
	}
	
	function clearDirections() {
		$("#directions_panel").html('');
	}
	
	function clearItinerary() {
		$('#itinerary_list').html('');
	}
                		
    function updateRoute() {
    	
    	// Remove all routes on map 
    	clearRoutes();
    	
    	// Remove all directions 
    	clearDirections();
    	
    	// Remove all waypoints on map 
    	clearWaypoints();
    	
    	// Get waypoints (start, end, waypoints)
    	var fromAddress = $('#fromAddress').val();
    	var toAddress = $('#toAddress').val();
    	var keyword = $('#place_keyword').val();
    	
    	// Get stops along adventure
    	//var routes = new Array();
        var waypoints = new Array();
	    waypointData = new Array();
	    waypointData.push({ location: fromAddress, travel_mode: $('#from_travel_type').val() }); // Push start point  
   		var waypointElements = $("#sortable").sortable('toArray'); // get array of waypoints from list
   		for(var i in waypointElements) {
    		//alert(waypoints[waypoint_id]);
    		var waypointSortableElementName = "#" + waypointElements[i];
    		var waypointElementName = waypointSortableElementName.substring(0, waypointSortableElementName.length - 4);
    		var waypointTravelModeElementName = waypointElementName + '_travel';
    		
    		var waypoint = $.trim($(waypointElementName).val());
    		var waypointTravelMode = $.trim($(waypointTravelModeElementName).val());
    		
    		//alert(stopTravelTypeSelect + ' = ' + stopTravelType);
    		if(waypoint.length > 0) {
    			waypoints.push({ location: waypoint });
    			waypointData.push({ location: waypoint, travel_mode: waypointTravelMode });
    		}
    	}
   		waypointData.push({ location: toAddress, travel_mode: null }); // Push end point 
   		
   		// Construct routes based on travel mode to waypoints in unprocessed waypoint data extracted from the UI
   		// - A route has only one mode of travel
   		if(Object.size(waypointData) > 1) {
   			// Initialize current route
   			var currentRoute = new Object();
   			currentRoute.origin = waypointData[0].location;
   			currentRoute.destination = null;
   			currentRoute.waypoints = new Array();
   			currentRoute.travelMode = getTravelMode(waypointData[0].travel_mode); // google.maps.DirectionsTravelMode.DRIVING
	   		
	   		var waypointDataLength = waypointData.length;
	   		for(var i = 1; i < waypointDataLength; i++) {
	   			//alert(waypointData[i].location + ":" + waypointData[i].travel_mode);
	   			
	   			if(getTravelMode(waypointData[i].travel_mode) !== currentRoute.travelMode) {
	   				
	   				// Push route onto array of routes
	   				currentRoute.destination = waypointData[i].location; // Set current waypoint as destination of previous route 
	   				routes.push(currentRoute); // Push route onto array of routes
	   				console.log("pushing route {" + currentRoute.origin + ", " + currentRoute.destination + ", " + Object.size(currentRoute.waypoints) + ", " + currentRoute.travelMode + "}");
	   				
	   				// Initialize new route if there are more waypoints 
	   				if (i < waypointDataLength - 1) {
		   				currentRoute = new Object();
		   				currentRoute.origin = waypointData[i].location;
		   	   			currentRoute.destination = null;
		   	   			currentRoute.waypoints = new Array();
		   	   			currentRoute.travelMode = getTravelMode(waypointData[i].travel_mode); // Set route travel mode
	   				}
	   				
	   			} else {
	   			
		   			// Add current overall waypoint to route's waypoints 
		   			currentRoute.waypoints.push({ location: waypointData[i].location });
	   			}
	   		}
    	} else {
    		alert("Error: There are fewer than two waypoints, so no routes can be constructed.");
    	}
   		
   		// Calculate route
    	calcRoute(routes, keyword);
    }
    
    function getTravelMode(travelMode) {
    	if(travelMode !== null) {
	    	travelMode = travelMode.toLowerCase();
	    	if(travelMode === "bicycling") {
	    		return google.maps.DirectionsTravelMode.BICYCLING;
	    	} else if(travelMode === "driving") {
	    		return google.maps.DirectionsTravelMode.DRIVING;
	    	} else if(travelMode === "transit") {
	    		return google.maps.DirectionsTravelMode.TRANSIT;
	    	} else if(travelMode === "walking") {
	    		return google.maps.DirectionsTravelMode.WALKING;
	    	}
    	} else {
    		return null;
    	}
    }
    
    
    function toggleItinerary() {
    	$('#itin').toggle();
    	$('#constraints').toggle();
    	
    	if($('#buttontoggle').val() === 'Make Itinerary') {
    		$('#buttontoggle').prop('value', 'Edit Route');
    	} else {
    		$('#buttontoggle').prop('value', 'Make Itinerary');
    	}
    	
    	// Clear itinerary
    	clearItinerary();
    	
    	// Populate itinerary
    	$.each(waypointData, function(index, value) {
    		if(index > 0) {
	    		var route = value;
	    		
	    		$('#itinerary_list').append('<div id="blah">');
	    		//alert( waypointData[index].travel_mode); 
	    		$('#itinerary_list').append('<h3>' + waypointData[index].travel_mode + '</h3>');
	    		
	    		// Add map for start point
	    		var waypointMap = '<table class="directions"><tr><th>Formatted Directions</th><th>Map</th></tr><tr><th>'
	    		+ '<input type="button" value="Gas Stations" onclick="javascript:addPlacesItinerary(\'gas_station\',' + index + ')"/>'
				+ '<input type="button" value="Hotels" onclick="javascript:addPlacesItinerary(\'lodging\',' + index + ')" />'
				+ '<input type="button" value="Restaurant" onclick="javascript:addPlacesItinerary(\'restaurant\',' + index + ')" /></th><th></th></tr><tr>'
	    	        + '<td valign="top"><div id="directions_panel_' + index + '" style="width: 275px"></div></td>'
	    	        + '<td valign="top"><div id="map_canvas_' + index + '" style="width: 640px; height: 320px"></div><td></tr></table>';
	    		$('#itinerary_list').append(waypointMap);
	    		
	    		// Add maps for waypoints
	    		//$.each(route.waypoints, function(j, waypoint) {
	    		//	var waypointMap = '<table class="directions"><tr><th>Formatted Directions</th><th>Map</th></tr><tr>'
	        	//        + '<td valign="top"><div id="directions_panel_' + index + '" style="width: 275px"></div></td>'
	        	//        + '<td valign="top"><div id="map_canvas_' + index + '_' + j + '" style="width: 640px; height: 480px"></div><td></tr></table>';
	        	//	$('#itinerary_list').append(waypointMap);
	    		//});
	    		
	    		// Add map for end point
	    		//var waypointMap = '<table class="directions"><tr><th>Formatted Directions</th><th>Map</th></tr><tr>'
	    	    //    + '<td valign="top"><div id="directions_panel_' + index + '_end" style="width: 275px"></div></td>'
	    	    //    + '<td valign="top"><div id="map_canvas_' + index + '_end" style="width: 640px; height: 480px"></div><td></tr></table>';
	    		//$('#itinerary_list').append(waypointMap);
	    		
	    		//$('#itinerary_list').append('</div>');
    		}
    	});
    	
    	// Create maps
    	initializeItinerary();
    	
    }
    </script>

	<style>
	#sortable {
		list-style-type: none;
		margin: 0;
		padding: 0;
		width: 60%;
	}
	
	#sortable li {
		margin: 0 3px 3px 3px;
		padding: 0.4em;
		padding-left: 1.5em;
		font-size: 1.4em;
		height: 18px;
	}
	
	#sortable li span {
		position: absolute;
		margin-left: -1.3em;
	}
	</style>
	
	<link href='http://fonts.googleapis.com/css?family=Average' rel='stylesheet' type='text/css'>
    
</head>

<body onload="initialize()" onunload="javascript:void(0);">

	<div id="header" style="background: url('./img/halfdomecliff.jpg') no-repeat center top; width: 100%; height: 400px; margin: 0px; padding: 0px; clear: both;">
		<div id="title" style="width: 300px; margin: 0px auto;">
			<h1 style="color: #000000; font-family: 'Average', serif; font-size: 37px; padding-top: 40px;">LM Adventures</h1>
		</div>
	</div>

	<div id="body" style="width: 1100px; margin: 0px auto;">
	
		<div id="controls">
		<input id="buttontoggle" type="button" value="Make Itinerary" onclick="javascript:toggleItinerary(); " />

		<div id="constraints" style="show: visible;">

			<!-- <form action="#" onsubmit="calcRoute(this.from.value, this.to.value); return false"> -->
			<form action="#" onsubmit="javascript:updateRoute(); return false;">
				<table>
					<tr>
						<th align="right">Starting point:&nbsp;</th>
						<td><input type="text" size="25" id="fromAddress" name="from"
							value="San Francisco" /> <select name="from_travel_type"
							id="from_travel_type"><option>Driving</option>
								<option>Transit</option>
								<option>Walking</option>
								<option>Bicycling</option></select>
							<td>
					</tr>
				</table>

				<!-- Waypoints -->
				<input type="button" value="Add Waypoint" onclick="addRow('waypointTable')" />
				<input type="button" value="Delete Waypoint" onclick="deleteRow('waypointTable')" />
				<table id="waypointTable" width="350px" border="1">
				</table>



				<script>
				$(function() {
					$("#sortable").sortable();
					$("#sortable").disableSelection();
				});
				</script>


				<div class="demo">
					<ul class="sortable" id="sortable">
					</ul>
				</div>





					<table>
						<tr>
							<td>
								<th align="right">&nbsp;&nbsp;Destination:&nbsp;</th>
								<td align="right"><input type="text" size="25" id="toAddress" name="to" value="Santa Cruz" />
							<td>
						</tr>
					</table>

					<table>
						<tr>
							<td>
								<th align="right">&nbsp;&nbsp;Keyword:&nbsp;</th>
								<td align="right"><input type="text" id="place_keyword" value="ice cream" />
							<td>
						</tr>
					</table>

					<input type="button" value="Update Route" onclick="javascript:updateRoute();" />

			</form>
			<input type="button" value="Gas Stations" onclick="javascript:addPlaces('gas_station')" />
			<input type="button" value="Hotels" onclick="javascript:addPlaces('lodging')" />
			<input type="button" value="Restaurant" onclick="javascript:addPlaces('restaurant')" />
			<br />

			<table class="directions">
				<tr>
					<th>Directions</th>
					<th>Map</th>
				</tr>
				<tr>
					<td valign="top">
						<div id="directions_panel" style="width: 275px"></div>
					</td>
					<td valign="top">
						<div id="map_canvas" style="width: 800px; height: 600px"></div>
					<td>
				</tr>
			</table>
		</div>

		<div id="itin" style="display: none;">
			<h1>Itinerary</h1>
			<div id="itinerary_list"></div>
		</div>
	</div>
	
	</div>

</body>
</html>